package org.jtb.flickrportlet;

import org.jtb.quickr.FlickrResponse.ErrorCode;
import org.jtb.quickr.FlickrResponseException;
import org.jtb.quickr.QuickrException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.PortletException;
import javax.portlet.PortletSecurityException;
import javax.portlet.UnavailableException;

import java.io.IOException;
import javax.portlet.PortletSession;

import javax.portlet.GenericPortlet;
import javax.portlet.PortletConfig;
import javax.portlet.PortletContext;
import javax.portlet.PortletRequest;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import org.apache.log4j.Logger;

public class FlickrPortlet extends GenericPortlet {
    private static Logger logger = Logger.getLogger(FlickrPortlet.class.getName());
    
    private PortletContext portletContext;
    
    public void init(PortletConfig config) throws PortletException {
        super.init(config);
        portletContext = config.getPortletContext();
    }
    
    public void doView(RenderRequest request,RenderResponse response) throws PortletException,IOException {
        PageHandler pageHandler;
        if (existsPageHandler(request)) {
            // use existing page handler in session
            pageHandler = getPageHandler(request);
        } else {
            // use new page handler with initial defaults
            // this is the first request and the JSP
            // has not created the bean yet
            pageHandler = new PageHandler();
        }
        
        String page = pageHandler.getPage();
        include(request, response, page);
    }
    
    /** Include "help" JSP. */
    public void doHelp(RenderRequest request,RenderResponse response) throws PortletException {
        include(request, response, "/help.jsp");
    }
    
    /** Include a page. */
    private void include(RenderRequest request, RenderResponse response, String page) throws PortletException {
        response.setContentType(request.getResponseContentType());
        if (page == null || page.length() == 0) {
            // assert
            throw new NullPointerException("null or empty page");
        }
        try {
            PortletRequestDispatcher dispatcher = portletContext.getRequestDispatcher(page);
            dispatcher.include(request, response);
        } catch (IOException ioe) {
            throw new PortletException(ioe);
        }
    }
    
    private static AuthHandler getAuthHandler(PortletRequest request) throws PortletException {
        AuthHandler authHandler = (AuthHandler)getSessionObject(request, "authHandler");
        return authHandler;
    }
    
    private static PageHandler getPageHandler(PortletRequest request) throws PortletException {
        PageHandler pageHandler = (PageHandler)getSessionObject(request, "pageHandler");
        return pageHandler;
    }
    
    private static PhotosBean getPhotosBean(PortletRequest request) throws PortletException {
        PhotosBean photosBean = (PhotosBean)getSessionObject(request, "photosBean");
        return photosBean;
    }

    private static ContactsBean getContactsBean(PortletRequest request) throws PortletException {
        ContactsBean contactsBean = (ContactsBean)getSessionObject(request, "contactsBean");
        return contactsBean;
    }
    
    private static PhotosHandler getPhotosHandler(PortletRequest request, PrefsBean prefsBean) throws PortletException, QuickrException {
        PhotosHandler photosHandler = (PhotosHandler)getSessionObject(request, "photosHandler");
        photosHandler.setPrefsBean(prefsBean);
        
        return photosHandler;
    }
    
    private static boolean existsPageHandler(PortletRequest request) throws PortletException {
        return existsSessionObject(request, "pageHandler");
    }
    
    private static boolean existsSessionObject(PortletRequest request, String name) throws PortletException {
        Object o = request.getPortletSession(true).getAttribute(name, PortletSession.APPLICATION_SCOPE);
        if (o == null) {
            return false;
        }
        
        return true;
    }
    
    private static Object getSessionObject(PortletRequest request, String name) throws PortletException {
        Object o = request.getPortletSession(true).getAttribute(name, PortletSession.APPLICATION_SCOPE);
        if (o == null) {
            throw new PortletException("could not get session object for name: " + name);
        }
        
        return o;
    }
    
    private static PrefsHandler getPrefsHandler(PortletRequest request) {
        PrefsBean prefsBean = new PrefsBean();
        PrefsHandler prefsHandler = new PrefsHandler();
        prefsHandler.setRequest(request);
        prefsHandler.setPrefsBean(prefsBean);
        
        return prefsHandler;
    }
    
    public void processAction(ActionRequest request, ActionResponse response) throws UnavailableException, PortletSecurityException, PortletException, IOException {
    	Resources resources = new Resources("resources.FlickrPortlet", request.getLocale());
    	
        try {
            // per-request
            PrefsHandler prefsHandler = getPrefsHandler(request);
            PrefsBean prefsBean = prefsHandler.getPrefsBean();
            
            // get objects from portlet application session
            // these are created by and shared w/ the JSP
            //
            // if any of these is not present in the session,
            // an exception will be thrown.
            AuthHandler authHandler = getAuthHandler(request);
            PageHandler pageHandler = getPageHandler(request);
            ContactsBean contactsBean = getContactsBean(request);
            PhotosBean photosBean = getPhotosBean(request);
            PhotosHandler photosHandler = getPhotosHandler(request, prefsBean);
            
            PhotoUploader uploader = new PhotoUploader(request, authHandler.getToken());
            if (uploader.isUploadRequest()) {
                if (uploader.upload()) {
                    photosBean.setLoaded(false);
                }
                pageHandler.setTabPage();
            } else {
                String action = request.getParameter("action");
                if (action == null) {
                    throw new PortletException("action was null");
                }
                
                if (action.equals("authenticate")) {
                    authHandler.authenticate();
                    prefsHandler.setUserName(authHandler.getUserName());
                    prefsHandler.store();
                    photosBean.setLoaded(false);
                } else if (action.equals("clear-user")) {
                    authHandler.clearToken();
                    prefsHandler.setUserName("");
                    prefsHandler.store();
                    photosBean.setLoaded(false);
                    photosHandler.resetPage();
                } else if (action.equals("next-page")) {
                    photosHandler.setPage(photosBean.getPage()+1);
                    photosBean.setLoaded(false);
                } else if (action.equals("delete")) {
                    String id = request.getParameter("id");
                    photosHandler.delete(id);
                    photosBean.setLoaded(false);
                    photosHandler.resetPage();
                } else if (action.equals("navigate-back")) {
                    pageHandler.setTabPage();
                } else if (action.equals("previous-page")) {
                    photosHandler.setPage(photosBean.getPage()-1);
                    photosBean.setLoaded(false);
                } else if (action.equals("goto-page")) {
                    String page = request.getParameter("page");
                    photosHandler.setPage(Integer.valueOf(page).intValue());
                    photosBean.setLoaded(false);
                } else if (action.equals("navigate-my")) {
                    pageHandler.setMyPage();
                    photosBean.setLoaded(false);
                    photosHandler.resetPage();
                } else if (action.equals("navigate-contacts")) {
                    pageHandler.setContactsPage();
                    photosBean.setLoaded(false);
                    photosHandler.resetPage();
                } else if (action.equals("navigate-search")) {
                    pageHandler.setSearchPage();
                    photosBean.setLoaded(false);
                    photosHandler.resetPage();
                } else if (action.equals("navigate-setUserName")) {
                    pageHandler.setSetUserNamePage();
                } else if (action.equals("navigate-add")) {
                    pageHandler.setAddPage();
                } else if (action.equals("select-contact")) {
                        String nsId = request.getParameter("selectedContact");
                        contactsBean.setSelectedContact(nsId);
                        photosBean.setLoaded(false);
                        photosHandler.resetPage();
                } else if (action.equals("set-user-name")) {
                    if (request.getParameter("submit") != null) {
                        String userName = request.getParameter("userNameInputText");
                        prefsHandler.setUserName(userName);
                        prefsHandler.store();
                        photosBean.setLoaded(false);
                        photosHandler.resetPage();
                        pageHandler.setTabPage();
                    }
                } else {
                    throw new PortletException("unknown action received: " + action);
                }
            }
        } catch (QuickrException qe) {
            if (qe instanceof FlickrResponseException) {
                FlickrResponseException fre = (FlickrResponseException)qe;
                if (fre.getErrorCode() == ErrorCode.INVALID_AUTH_TOKEN) {
                    // clear authentication, force user to re-auth
                    AuthHandler authHandler = getAuthHandler(request);
                    authHandler.clearToken();
                }
            }
            request.getPortletSession().setAttribute("processActionException", qe, PortletSession.APPLICATION_SCOPE);
        } catch (PortletException pe) {
            request.getPortletSession().setAttribute("processActionException", pe, PortletSession.APPLICATION_SCOPE);
        }
    }
}
